package com.m2soft.controls.flashviewer
{
	import com.m2soft.controls.FlowVBox;
	import com.m2soft.controls.ZoomCanvas;
	import com.m2soft.events.CurrentPageChangedEvent;
	import com.m2soft.events.CursorModeChangedEvent;
	import com.m2soft.events.FitModeChangedEvent;
	import com.m2soft.events.ScaleChangedEvent;
	import com.m2soft.events.SelectionCreatedEvent;
	import com.m2soft.streaming.DupImage;
	import com.m2soft.transitions.Tweener;
	
	import flash.accessibility.AccessibilityProperties;
	import flash.display.*;
	import flash.events.*;
	import flash.filters.DropShadowFilter;
	import flash.geom.*;
	import flash.net.*;
	import flash.printing.*;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.System;
	import flash.ui.Keyboard;
	import flash.utils.Timer;
	import flash.utils.setTimeout;
	
	import mx.containers.Canvas;
	import mx.controls.Alert;
	import mx.controls.Image;
	import mx.core.Container;
	import mx.core.SpriteAsset;
	import mx.core.UIComponent;
	import mx.managers.CursorManager;
	
	[Event(name="onStatusChanged", type="flash.events.Event")]

	[Event(name="onDocumentLoading", type="flash.events.Event")]
	[Event(name="onNoMoreSearchResults", type="flash.events.Event")]
	[Event(name="onLoadingProgress", type="flash.events.ProgressEvent")]
	[Event(name="onScaleChanged", type="com.m2soft.events.ScaleChangedEvent")]
	[Event(name="onExternalLinkClicked", type="com.m2soft.events.ExternalLinkClickedEvent")]
	[Event(name="onCurrPageChanged", type="com.m2soft.events.CurrentPageChangedEvent")]
	[Event(name="onViewModeChanged", type="com.m2soft.events.ViewModeChangedEvent")]
	[Event(name="onFitModeChanged", type="com.m2soft.events.FitModeChangedEvent")]
	[Event(name="onCursorModeChanged", type="com.m2soft.events.CursorModeChangedEvent")]
	[Event(name="onDocumentLoadedError", type="flash.events.ErrorEvent")]
	[Event(name="onLogoClicked", type="flash.events.Event")]
	[Event(name="onSelectionCreated", type="com.m2soft.events.SelectionCreatedEvent")]
	
	public class ReportViewer extends Canvas
	{
		private var _rdReport : RDReport;			// rd report contents
		private var _paperContainer:ZoomCanvas;
		private var _displayContainer:Container;
		private var _pageCanvas : DupImage = null;		// this - _paperContainer - _displayContainer - _pageCanvas - RDReport.loader
		private var _swfContainer:Canvas; 

		private var _viewshowmode : int = 0;	// 0, 1, 2, 3, 4
		private var _fitMode:String = FitModeEnum.FITPAGE; 
		private var _scale:Number = 1;
		
		private var _init_scale : Number = 0;
		private var _requestPages : int = 10;
		
		private var m_BackgroundColor : int = 0x808080;
		private var m_OwnerPassword : String = null;
		private var m_UserPassword : String = null;
		
		private var _tweencount:Number = 0;
		private var _zoomtransition:String = "easeOut";
		private var _zoomtime:Number = 0.6; 
		private var _dupImageClicked:Boolean = false;
		private var _repaintTimer:Timer;
		private var loaderCtx:LoaderContext;
		private var _zoomInterval:Number = 0;
		private var _cursorsEnabled:Boolean = true;
		private var _grabCursorID:Number = 0;
		private var _grabbingCursorID:Number = 0;
		
		[Embed(source="/../assets/grab.gif")]
		private var grabCursor:Class;	  
		
		[Embed(source="/../assets/grabbing.gif")]
		private var grabbingCursor:Class;

		//
		public function ReportViewer()
		{

			super();

			_rdReport = new RDReport();
			_pageCanvas = null;
		}

		//
		public function ViewShowMode(mode : int):void 
		{
			_viewshowmode = mode;
		}
		
		//
		public function ZoomDefault() : void
		{
			if (_init_scale == 0)
				return;
				
			Zoom(_init_scale);
		}
			
		//
		public function SetZoomRatio(ratio : int) : int 
		{
			var old : int = _scale * 100;
			
			if (_fitMode != FitModeEnum.FITNONE)
				return old;
			
			var vnew : Number = ratio / 100.0;
				
			Zoom(vnew);
			 
			return old;
		}
		
		// 
		public function SetRequestPage(nPages : int) : void
		{
			_requestPages = nPages;
		}
		
		//
		public function loadReport(url : String, mrd_path : String, mrd_param : String, mrd_data : String):void 
		{
			_rdReport.Clear();
			
			createDisplayContainer();
			
			// Changing the SWF file causes the component to invalidate.
			invalidateProperties();
			invalidateSize();
			invalidateDisplayList();
			
			_rdReport.setParam(url, mrd_path, mrd_param, mrd_data, 
					getExecutionContext(),
					pageCountChangedHandler,
					statusChangedHandler,
					pageChangedHandler,
					documentLoadedErrorHandler,
					httpResponseHandler,
					_viewshowmode
				);
			
			_rdReport.loadReport();
		}
		
		public function resetPage(): void
		{
			_rdReport.resetPage();
		}
		
		// kth add 2012.04.18
		public function isReportDone(): Boolean
		{
			return _rdReport.isReportDone();
		}

		// kth add 2012.04.12
		public function updateAccessibilityProp():void
		{
			if (!_rdReport.accessibility_active)
				return;
			
			var textContent: String = getAccessibilityText(currPage);
			var chartAccessibiltiyProperties:flash.accessibility.AccessibilityProperties;
			
			if (!accessibilityProperties)
				chartAccessibiltiyProperties = new AccessibilityProperties();
			else
				chartAccessibiltiyProperties = accessibilityProperties;
			
			chartAccessibiltiyProperties.forceSimple = true;
			chartAccessibiltiyProperties.name = textContent;
			flash.accessibility.Accessibility.updateProperties();
		}

		// kth add 2012.04.12
		public function setAccessibilityHandler():void
		{
			_rdReport.setAccessibilityHandler(updateAccessibilityProp);
		}
		
		//
		public function SetPdfPassword(ownerPassword : String, userPassword : String) : void
		{
			m_OwnerPassword = ownerPassword;
			m_UserPassword = userPassword;
		}
		
		//
		public function SaveReportFile(type : String) : void
		{
			_rdReport.SaveReportFile(type, m_OwnerPassword, m_UserPassword);
		}
		
		//
		public function getReportFile(type : String) : String
		{
			return _rdReport.getReportFile(type, m_OwnerPassword, m_UserPassword);
		}
		
		//
		override protected function createChildren():void 
		{
			// Call the createChildren() method of the superclass.
			super.createChildren();
			
			this.styleName = "viewerBackground";
			
			// Bind events
			addEventListener(Event.RESIZE, sizeChanged);
			systemManager.stage.addEventListener(KeyboardEvent.KEY_DOWN, keyboardHandler);
			
			// Create a visible container for the swf
			_swfContainer = new Canvas();
			_swfContainer.visible = false;
			_swfContainer.styleName = "viewerBackground";
			_swfContainer.setStyle('fillColors', [0xFFFFFF, 0xFFFFFF]);
			this.addChild(_swfContainer);
			
			// Create a timer to use for repainting
			_repaintTimer = new Timer(100,0);
			_repaintTimer.start();
			_repaintTimer.addEventListener("timer", repaintHandler);
		}

		// 
		private function createDisplayContainer():void
		{
			// Add the swf to the invisible container.
			_swfContainer.removeAllChildren();
			
			for(var i:int=0; i<8; i++)
				_swfContainer.addChild(new UIComponent());

			// remove _paperContainer
			if(_paperContainer !=null && _paperContainer.parent == this)
			{
				removeChild(_paperContainer);
				_paperContainer.removeEventListener(MouseEvent.MOUSE_WHEEL, wheelHandler);
			}
				
			// create _paperContainer
			_paperContainer = new ZoomCanvas();
			_paperContainer.percentHeight = 100;
			_paperContainer.percentWidth = 100;
			_paperContainer.x = -1;
			_paperContainer.y = -1;
			_paperContainer.verticalScrollPosition = 0;
			_paperContainer.addEventListener(MouseEvent.MOUSE_WHEEL, wheelHandler);
			_paperContainer.addEventListener(KeyboardEvent.KEY_DOWN, keyboardHandler);

			this.setStyle('fillColors', [m_BackgroundColor, m_BackgroundColor]);

			addChildAt(_paperContainer,0);
			
			try
			{
				new flash.net.LocalConnection().connect('m2softGCdummy');
			} catch (e:*) {}
			
			try{flash.system.System.gc();} catch (e:*) {}
			
			// remove _displayContainer;
			if(_paperContainer.numChildren > 0)
				_paperContainer.removeAllChildren();
				
			if (_displayContainer != null)
			{
				_displayContainer.removeAllChildren();
				_displayContainer.removeEventListener(MouseEvent.ROLL_OVER,displayContainerrolloverHandler);
				_displayContainer.removeEventListener(MouseEvent.ROLL_OUT,displayContainerrolloutHandler);
				_displayContainer.removeEventListener(MouseEvent.MOUSE_DOWN,displayContainerMouseDownHandler);
				_displayContainer.removeEventListener(MouseEvent.MOUSE_UP,displayContainerMouseUpHandler);
				_displayContainer.removeEventListener(MouseEvent.DOUBLE_CLICK,displayContainerDoubleClickHandler);
			}
			
			// create _displayContainer
			_displayContainer = new FlowVBox();
			_paperContainer.addChild(_displayContainer);
			_paperContainer.childrenDoDrag = true;
			
			_displayContainer.verticalScrollPolicy = "off";
			_displayContainer.horizontalScrollPolicy = "off";	
			
			if (_viewshowmode == 0)
			{
				_displayContainer.setStyle("horizontalAlign", "center");
				_displayContainer.setStyle("verticalAlign", "middle");
			}
			else if (_viewshowmode == 1 || _viewshowmode == 2)
			{
				_displayContainer.setStyle("horizontalAlign", "left");
				_displayContainer.setStyle("verticalAlign", "top");
			}
			else if (_viewshowmode == 3)
			{
				_displayContainer.setStyle("horizontalAlign", "center");
				_displayContainer.setStyle("verticalAlign", "top");
			}
			else if (_viewshowmode == 4)
			{
				_displayContainer.setStyle("horizontalAlign", "left");
				_displayContainer.setStyle("verticalAlign", "middle");
			}
			else
			{
				_displayContainer.setStyle("horizontalAlign", "center");
				_displayContainer.setStyle("verticalAlign", "middle");
			}
			
			_displayContainer.percentHeight = 100;
			_displayContainer.percentWidth = 96;
			_displayContainer.useHandCursor = true;
			_displayContainer.addEventListener(MouseEvent.ROLL_OVER,displayContainerrolloverHandler);
			_displayContainer.addEventListener(MouseEvent.ROLL_OUT,displayContainerrolloutHandler);
			_displayContainer.addEventListener(MouseEvent.MOUSE_DOWN,displayContainerMouseDownHandler);
			_displayContainer.addEventListener(MouseEvent.MOUSE_UP,displayContainerMouseUpHandler);
			_displayContainer.addEventListener(MouseEvent.DOUBLE_CLICK,displayContainerDoubleClickHandler);
			_displayContainer.doubleClickEnabled = true;
		}
		
		//
		public function pageCountChangedHandler(count : int) : void
		{
			dispatchEvent(new Event("onStatusChanged"));
		}

		//
		public function statusChangedHandler() : void
		{
			dispatchEvent(new Event("onStatusChanged"));
		}
		
		// 
		public function httpResponseHandler(opcode : String) : void
		{
			if (m_printJob != null && opcode == "602")
			{
				printPage();
			}
		}
		
		// 
		public function pageChangedHandler(pageno : int) : void
		{
			if (pageno != _rdReport.currentPage)
				return;
			
			if (_rdReport.getMmlType() == 1) {
				if(pageno == 1)
					_rdReport.changePage(pageno);
			}
			else
				repositionPapers();
			dispatchEvent(new Event("onStatusChanged"));
		}
			
		//
		public function documentLoadedErrorHandler(message : String) : void
		{
			var evt : ErrorEvent = new ErrorEvent("onDocumentLoadedError");
			evt.text = message;
			dispatchEvent(evt);
		}
		
		//
		public function SetPageColor(rgb : uint):void
		{
			DupImage.SetPageColor(rgb);
			
			if (_pageCanvas != null)
				_pageCanvas.invalidateDisplayList();
		} 

		//
		public function SetPageLineColor(rgb : uint):void
		{
			DupImage.SetPageLineColor(rgb);
			
			if (_pageCanvas != null)
				_pageCanvas.invalidateDisplayList();
		} 
		
		//
		public function SetBackgroundColor(rgb : uint):void
		{
			m_BackgroundColor = rgb;
			this.setStyle('fillColors', [m_BackgroundColor, m_BackgroundColor]);
		} 
		
		//		
		public function gotoPage(p:Number):void
		{
			if( p < 1 || p > _rdReport.pageCount)
				return;
			
			var old : int = _rdReport.currentPage;
			
			_rdReport.gotoPage(p, p+_requestPages-1);
			
			if (_rdReport.getMmlType() == 0)
				repositionPapers();

			if (old != _rdReport.currentPage)
				dispatchEvent(new Event("onStatusChanged"));
		}
		
		// kth add 2012.04.12
		public function getAccessibilityText(page:int): String
		{
			return _rdReport.getAccessibilityText(page);
		}

		// kth add 2012.04.12
		public function setAccessibilityActive(active:Boolean): void
		{
			return _rdReport.setAccessibilityActive(active);
		}

		// kth add 2012.04.12
		public function setAccessibilityOpt(opt:int): void
		{
			_rdReport.setAccessibilityOpt(opt);;
		}
		
		// kth #1461 [한국대학교육협의회] Flash Reporting 동작 방식 변경
		public function setSwfStreamOpt(opt:int): void
		{
			_rdReport.setSwfStreamOpt(opt);;
		}

		// kth 2343 [Flash Viewer] mml 포맷을 읽어서 표현하도록 지원. head, page별 xml 저장함
		public function setMmlType(type: int): void
		{
			_rdReport.setMmlType(type);
		}
		
		// kth add 2012.08.21.
		public function setProgressTimeout(timeout:int): void
		{
			_rdReport.setProgressTimeout(timeout);;
		}
		
		// 
		private function repositionPapers():void
		{
			if (_rdReport == null)
				return;
				
			// remove _pageCanvas
			if (_pageCanvas != null)
			{
				if (_pageCanvas.parent != null)
					_pageCanvas.parent.removeChild(_pageCanvas);
				_pageCanvas.removeAllChildren();
				_pageCanvas.source = null;
				
				_pageCanvas.removeEventListener(MouseEvent.MOUSE_OVER,dupImageMoverHandler);
				_pageCanvas.removeEventListener(MouseEvent.MOUSE_OUT,dupImageMoutHandler);
				_pageCanvas.removeEventListener(MouseEvent.CLICK,dupImageClickHandler);
				
				_pageCanvas = null;
			}
			
			if (_rdReport.pageLoader == null)
				return;
			
			_pageCanvas = new DupImage(); 
			
			_pageCanvas.scaleX = _pageCanvas.scaleY = _scale;
			
			_pageCanvas.width = _rdReport.width;
			_pageCanvas.height = _rdReport.height;
			_pageCanvas.addChild(_rdReport.pageLoader);
			_pageCanvas.addEventListener(MouseEvent.MOUSE_OVER,dupImageMoverHandler);
			_pageCanvas.addEventListener(MouseEvent.MOUSE_OUT,dupImageMoutHandler);
			_pageCanvas.addEventListener(MouseEvent.CLICK,dupImageClickHandler);
			
			_displayContainer.addChild(_pageCanvas);

			switch(_fitMode)
			{					
				case FitModeEnum.FITWIDTH:
					fitWidth();
					break;
				
				case FitModeEnum.FITPAGE:
					fitPage();
					break;										
			}
			
			if (_init_scale == 0)
				_init_scale = _scale;
		}
		
		//
		public function get numPages():int 
		{
			return _rdReport.pageCount;
		}	
		
		//
		public function get currPage():int 
		{
			return _rdReport.currentPage;
		}	
		
		//
		public function get status():int
		{
			return _rdReport.status;
		}
		
		//
		public function get saving():Boolean
		{
			return _rdReport.saving;
		}
		
		//
		public function get printing():Boolean
		{
			return (m_printJob != null) ? true : false;
		}
		
		//
		public function get pageLoaded():Boolean
		{
			var page : Loader = _rdReport.pageLoader;
			
			if (page == null)
				return false;
			else
				return true;
		}
		
		//
		public function cancelLoad() : void
		{
			// cancel print
			if (m_printJob != null)
			{
				m_printJob = null;
			}
			
			// cancel loading
			_rdReport.cancelLoad();
		}

		//
		public function SetAutoAdjust(mode : int) : int 
		{
			var vold : int;
			vold = (_fitMode == FitModeEnum.FITNONE) ? 0 : (_fitMode == FitModeEnum.FITPAGE ? 1 : 2);
			
			var vnew : String = (mode == 0) ? FitModeEnum.FITNONE : (mode == 1 ? FitModeEnum.FITPAGE : FitModeEnum.FITWIDTH);
			
			if (_rdReport.status == RDReport.STATUS_INIT)
			{
				_fitMode = vnew;				
				return vold;
			}
			
			FitMode = vnew;
			
			return vold;
		}
		
		//
		[Bindable]
		public function get FitMode():String 
		{
			return _fitMode;
		}	
		
		//
		public function set FitMode(s:String):void 
		{
			if(s!=_fitMode){
				_fitMode = s;
				
				switch(s){					
					case FitModeEnum.FITWIDTH:
						fitWidth();
						break;
					
					case FitModeEnum.FITPAGE:
						fitPage();
						break;										
				}
				
				dispatchEvent(new FitModeChangedEvent(FitModeChangedEvent.FITMODE_CHANGED,_fitMode));
			}
		}
		
		[Bindable]
		public function get CursorsEnabled():Boolean {
			return _cursorsEnabled;
		}	

		public function set CursorsEnabled(b:Boolean):void {
			 _cursorsEnabled = b;
		}	
				
		public function setPaperFocus():void{
			_paperContainer.setFocus();
		}
		
		public function get ZoomTransition():String {
			return _zoomtransition;
		}	
		
		public function set ZoomTransition(s:String):void {
			_zoomtransition = s;
		}
		
		public function get ZoomTime():Number {
			return _zoomtime;
		}	
		
		public function set ZoomTime(n:Number):void {
			_zoomtime = n;
		}		
		
		public function get ZoomInterval():Number {
			return _zoomInterval;
		}	
		
		public function set ZoomInterval(n:Number):void {
			_zoomInterval = n;
		}				
		
		public function get PaperVisible():Boolean {
			return _paperContainer.visible;
		}

		public function set PaperVisible(b:Boolean):void {
			_paperContainer.visible = b;
		}
		
		[Bindable]
		public function get Scale():String {
			return _scale.toString();
		}		
		
		public function ZoomPlus():void
		{
			var factor : Number = _scale * 1.3;
			Zoom(factor);
		}

		public function ZoomMinus():void
		{
			var factor : Number = _scale / 1.3;
			Zoom(factor);
		}

		public function Zoom(factor:Number):void
		{
			if(factor<0.25)
				factor = 0.25;
			
			if (factor > 4)
				factor = 4;

			if(factor == _scale)
				return;
			
			if (_rdReport.status == RDReport.STATUS_INIT)
			{
				_scale = factor;				
				return;
			}
			
			var _target:DisplayObject;
			_paperContainer.CenteringEnabled = (_paperContainer.width>0);
			
			_tweencount = _displayContainer.numChildren;
			
			for(var i:int=0;i<_displayContainer.numChildren;i++){
				_target = _displayContainer.getChildAt(i);
				_target.filters = null;
				Tweener.addTween(_target, {scaleX: factor, scaleY: factor, time: _zoomtime, transition: _zoomtransition, onComplete: tweenComplete});
			}
			
			FitMode = FitModeEnum.FITNONE;
			_scale = factor;
			
			dispatchEvent(new ScaleChangedEvent(ScaleChangedEvent.SCALE_CHANGED,_scale));
		}
		
		private function getFitWidthFactor():Number
		{
			if (_rdReport.pageLoader == null)
				return 1;

			return (_paperContainer.width / _rdReport.width) - 0.032; //- 0.03;
		}
		
		private function getFitPageFactor():Number
		{
			if (_rdReport.pageLoader == null)
				return 1;
			
			var factor_w : Number = (_paperContainer.width / _rdReport.width) - 0.032;
			var factor_h : Number = (_paperContainer.height / _rdReport.height);
			
			return  Math.min(factor_w, factor_h);
		}
		
		public function fitWidth():void
		{
			if(_displayContainer == null || _displayContainer.numChildren == 0){return;}
			
			var _target:DisplayObject;
			_paperContainer.CenteringEnabled = (_paperContainer.width>0);
			var factor:Number = getFitWidthFactor();
			_scale = factor;
			_tweencount = _displayContainer.numChildren;
			
			for(var i:int=0;i<_displayContainer.numChildren;i++){
				_target = _displayContainer.getChildAt(i);
				_target.filters = null;
				Tweener.addTween(_target, {scaleX:factor, scaleY:factor,time: 0, transition: 'easenone', onComplete: tweenComplete});
			}
			
			FitMode = FitModeEnum.FITWIDTH;
			
			dispatchEvent(new ScaleChangedEvent(ScaleChangedEvent.SCALE_CHANGED,_scale));
		}
		
		public function fitPage():void
		{
			if(_displayContainer == null || _displayContainer.numChildren == 0){return;}
			
			var _target:DisplayObject;
			_paperContainer.CenteringEnabled = (_paperContainer.height>0);
			
			var factor:Number = getFitPageFactor(); 
			_scale = factor;
			_tweencount = _displayContainer.numChildren;
			
			for(var i:int=0;i<_displayContainer.numChildren;i++)
			{
				_target = _displayContainer.getChildAt(i);
				_target.filters = null;
				Tweener.addTween(_target, {scaleX:factor, scaleY:factor,time: 0, transition: 'easenone', onComplete: tweenComplete});
			}			
			
			_fitMode = FitModeEnum.FITPAGE;
			
			dispatchEvent(new ScaleChangedEvent(ScaleChangedEvent.SCALE_CHANGED,_scale));
		}
		
		private function tweenComplete():void
		{
			_tweencount--;
						
			if(_tweencount==0)
			{
//				repositionPapers();
			}
		}
		
		public function set Scale(s:String):void 
		{
			var diff:Number = _scale - new Number(s);
			_scale = new Number(s);
		}		
		
		private function repaintHandler(e:Event):void 
		{
			var loader : Loader = _rdReport.pageLoader;
			
			if (loader == null || loader.parent != null)
				return;
			
			_pageCanvas.removeAllChildren();
			_pageCanvas.addChild(loader);			
		}
		
		private function displayContainerrolloverHandler(event:MouseEvent):void
		{
			_grabCursorID = CursorManager.setCursor(grabCursor);
		}
		
		private function displayContainerMouseUpHandler(event:MouseEvent):void
		{
			CursorManager.removeCursor(_grabbingCursorID);
			_grabCursorID = CursorManager.setCursor(grabCursor);
		}
		
		private function displayContainerDoubleClickHandler(event:MouseEvent):void
		{
			FitMode = (FitMode == FitModeEnum.FITWIDTH) ? FitModeEnum.FITPAGE:FitModeEnum.FITWIDTH; 
		}
		
		private function displayContainerMouseDownHandler(event:MouseEvent):void
		{
			CursorManager.removeCursor(_grabCursorID);
			_grabbingCursorID = CursorManager.setCursor(grabbingCursor);
		}
		
		private function displayContainerrolloutHandler(event:Event):void
		{
			CursorManager.removeAllCursors();
		}		
		
		private function wheelHandler(evt:MouseEvent):void 
		{
			_paperContainer.removeEventListener(MouseEvent.MOUSE_WHEEL, wheelHandler);
			
			var t:Timer = new Timer(1,1);
			t.addEventListener("timer", addMouseScrollListener);
			t.start();
			
			_paperContainer.dispatchEvent(evt.clone());
		}
		
		private function addMouseScrollListener(e:Event):void 
		{
			_paperContainer.addEventListener(MouseEvent.MOUSE_WHEEL, wheelHandler);
		}		
		
		private function keyboardHandler(event:KeyboardEvent):void
		{
			if(event.keyCode == Keyboard.DOWN){
				_paperContainer.verticalScrollPosition = _paperContainer.verticalScrollPosition + 10;	
			}
			
			if(event.keyCode == Keyboard.UP){
				_paperContainer.verticalScrollPosition = _paperContainer.verticalScrollPosition - 10;
			}
			
			if(event.keyCode == Keyboard.PAGE_DOWN){
				_paperContainer.verticalScrollPosition = _paperContainer.verticalScrollPosition + 300;  
			}
			if(event.keyCode == Keyboard.PAGE_UP){
				_paperContainer.verticalScrollPosition = _paperContainer.verticalScrollPosition - 300;  
			}
			if(event.keyCode == Keyboard.HOME){
				_paperContainer.verticalScrollPosition = 0;
			}
			if(event.keyCode == Keyboard.END){
				_paperContainer.verticalScrollPosition = _paperContainer.maxVerticalScrollPosition;
			}
		}
		
		private function sizeChanged(evt:Event):void
		{
			if (_rdReport == null)
				return;
				
			switch(_fitMode)
			{					
				case FitModeEnum.FITWIDTH:
					fitWidth();
					break;
				
				case FitModeEnum.FITPAGE:
					fitPage();
					break;										
			}
		}
		
		private function skinMouseOver(evt:MouseEvent):void{
		}
	
		private function skinMouseOut(evt:MouseEvent):void{
		}

		private function skinMouseDown(evt:MouseEvent):void{
			dispatchEvent(new Event("onLogoClicked"));
		}
		
		private function onLoadProgress(event:ProgressEvent):void{
			var e:ProgressEvent = new ProgressEvent("onLoadingProgress")
			e.bytesTotal = event.bytesTotal;
			e.bytesLoaded = event.bytesLoaded;
			dispatchEvent(e);
		}
		
		private function dupImageClickHandler(event:MouseEvent):void
		{
			stage.stageFocusRect = false;
			stage.focus = event.target as InteractiveObject;
			
			_dupImageClicked = true;
			var t:Timer = new Timer(100,1);
			t.addEventListener("timer", resetClickHandler);
			t.start();				
		}
		
		private function resetClickHandler(e:Event):void {
			_dupImageClicked = false;
		}
		
		private function dupImageMoverHandler(event:MouseEvent):void
		{
			if(event.target is flash.display.SimpleButton || event.target is SpriteAsset || (event.target is IFlexPaperPluginControl) || (event.target.parent !=null && event.target.parent.parent !=null && event.target.parent.parent is IFlexPaperPluginControl)){
				CursorManager.removeAllCursors();
			}else{
				_grabCursorID = CursorManager.setCursor(grabCursor);
			}
		}
		
		private function dupImageMoutHandler(event:MouseEvent):void
		{
		}
		
		// print param
		private var m_printJob : PrintJob = null;

		private var m_PrintRange : Array;
		private var m_PrintRangeSent : Array;
		private var m_OffsetX : int = 0;
		private var m_OffsetY : int = 0;
		private var m_Copy : int = 1;
		private var m_CopyType : int = 0;		// 0: page, 1: total
		private var m_ExpandType : int = 0;		// 0: paper size, 1: Manual, 2: multi pages
		private var m_ExpandRate : Number = 1;	// 0.25 ~ 4 (only for 1)
		private var m_MultiPages : int = 1;		// 1, 2, 4, 6, 8	(only for 2)
		
		public function printReport(
				_PrintRange : Array,
				_OffsetX : int = 0,
				_OffsetY : int = 0,
				_Copy : int = 1,
				_CopyType : int = 0,		// 0: page, 1: total
				_ExpandType : int = 0,		// 0: paper size, 1: Manual, 2: multi pages
				_ExpandRate : Number = 1,	// 0.25 ~ 4 (only for 1)
				_MultiPages : int = 1		// 1, 2, 4, 6, 8	(only for 2)
			) : void
		{
			if (m_printJob != null)
				return;
			
			m_PrintRange = _PrintRange;
			m_PrintRangeSent = new Array();
			m_OffsetX = _OffsetX;
			m_OffsetY = _OffsetY;
			m_Copy = _Copy;
			m_CopyType = _CopyType;
			m_ExpandType = _ExpandType;
			m_ExpandRate = _ExpandRate;
			m_MultiPages = _MultiPages;

			m_printJob = new PrintJob();
			
			statusChangedHandler();

			printPage();		
		}
		
		public function cancelPrint() : void
		{
			m_printJob = null;
			statusChangedHandler();
		}
		
		public function printPage() : void
		{
			if (m_printJob == null)
				return;
			
			var page : int;
			var i : int;
			
			// check all requested
			for(i=0; i<m_PrintRange.length; i++)
			{
				page = m_PrintRange[i];
				
				if (!_rdReport.isPageLoaded(page, page) && m_PrintRangeSent.indexOf(page) == -1)
				{
					var p1 : int = page;
					var p2 : int = page + _requestPages - 1;
					_rdReport.loadPage(p1, p2);
					
					for(var k:int=p1; k<=p2; k++)
						m_PrintRangeSent.push(k);
						
					return;
				}
			}
			
			// check all loaded
			for(i=0; i<m_PrintRange.length; i++)
			{
				page = m_PrintRange[i];
				
				if (!_rdReport.isPageLoaded(page, page))
				{
					flash.utils.setTimeout(printPage, 100);						
					return;
				}
			}

			// start print
			if(!m_printJob.start())
			{
				m_printJob = null;
				statusChangedHandler();
			
				return;
			}
			
			var options:PrintJobOptions = new PrintJobOptions();
			var uic : UIComponent;
			var loader : Loader;
			
			var curPage : int = _rdReport.currentPage;
			var curLoader : Loader = _rdReport.pageLoader;
					
			for (var cp:int=0; cp<(m_CopyType==0 ? 1 : m_Copy); cp++)
			{
				var p : int = 0;
				
				for(i=0; i<Math.ceil(m_PrintRange.length / m_MultiPages); i++)
				{
					var arr_uic : Array = new Array();
					var arr_loader : Array = new Array();
					var co : int;
					var inSeroFlag : int;
					//var rationFlag : int;
					
					for(co=0; co<m_MultiPages && p<m_PrintRange.length; co++)
					{
						page = m_PrintRange[p];
						p++;
						
						_rdReport.gotoPage(page, page + _requestPages - 1);
						
						uic = (_swfContainer.getChildAt(co) as UIComponent);
						loader = _rdReport.pageLoader;
			
						// ikchoi 2012.02.21
						if (co == 0)
						{
							if (loader.width > loader.height)
							{
								inSeroFlag = 0;	
							}
							else
							{
								inSeroFlag = 1;
							}
						}
						
						if (isRotation (loader) == 1)
						{
							loader.rotation = 90;
						}
						
						uic.addChild(loader);
						loader.alpha = 1;
						
						arr_uic.push(uic);
						arr_loader.push(loader);
					}
					
					// set page position
			    	if (m_ExpandType == 0)
			    	{
			    		loader = arr_loader[0];
			    		uic = arr_uic[0];
						
						if((m_printJob.pageHeight/_rdReport.height) < (m_printJob.pageWidth/_rdReport.width))
							loader.scaleX = loader.scaleY = (m_printJob.pageHeight/_rdReport.height);
						else
							loader.scaleX = loader.scaleY = (m_printJob.pageWidth/_rdReport.width);
											
						uic.x = m_OffsetX * 2.835 / 10;
						uic.y = m_OffsetY * 2.835 / 10;
			    	}
			    	else if (m_ExpandType == 1)
			    	{
			    		loader = arr_loader[0];
			    		uic = arr_uic[0];
			    		
						loader.scaleX = loader.scaleY = m_ExpandRate;
						
						uic.x = m_OffsetX * 2.835 / 10;
						uic.y = m_OffsetY * 2.835 / 10;
			    	}
			    	else
			    	{
			    		var pw : int;
			    		var ph : int;

						pw = m_printJob.pageWidth;
						ph = m_printJob.pageHeight;
							
						switch (m_MultiPages)
						{
							case 1:
								break;
							case 2:
								if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
								{
									pw = pw / 2;
									ph = ph;
								}
								else
								{
									pw = pw;
									ph = ph / 2;
								}
								break;
							case 4:
								pw = pw / 2;
								ph = ph / 2;
								break;
							case 6:
								if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
								{
									pw = pw / 3;
									ph = ph / 2;
								}
								else
								{
									pw = pw / 2;
									ph = ph / 3;
								}
								break;
							case 8:
								if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
								{
									pw = pw / 4;
									ph = ph / 2;
								}
								else
								{
									pw = pw / 2;
									ph = ph / 4;
								}
								break;
						}

						var scale : Number;

						if((ph /_rdReport.height) < (pw /_rdReport.width))
						{
							scale = (ph /_rdReport.height);
						}
						else
						{
							scale = (pw /_rdReport.width);
						}
			    		
						for(co=0; co<m_MultiPages && co<arr_loader.length; co++)
						{
							loader = arr_loader[co];
							uic = arr_uic[co];
							
							loader.scaleX = loader.scaleY = scale;
							
							switch(co+1)
							{
								case 1:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										switch (m_MultiPages)
										{
											case 1 :
												uic.x = 0;
												uic.y = 0;
												break;
											case 2 :
												if (inSeroFlag == 1)
												{
													uic.x = 0;
													uic.y = 0;
												}
												else
												{
													uic.x = pw;
													uic.y = 0;
												}
												break;
											case 4 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = 0;
												}
												else
												{
													uic.x = 0;
													uic.y = 0;
												}
												break;
											case 6 :
												if (inSeroFlag == 1)
												{
													uic.x = 0;
													uic.y = 0;
												}
												else
												{
													uic.x = pw*2;
													uic.y = 0;
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{
													uic.x = 0;
													uic.y = 0;
												}
												else
												{
													uic.x = pw*3;
													uic.y = 0;
												}
										}
									}
									else
									{
										switch (m_MultiPages)
										{
											case 1 :
											case 2 :
												uic.x = 0;
												uic.y = 0;
												break;
											case 4 :
												if (inSeroFlag == 0)
												{
													uic.x = pw;
													uic.y = 0;
												}
												else
												{
													uic.x = 0;
													uic.y = 0;
												}
												break;
											case 6 :
											case 8 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = 0;
												}
												else
												{
													uic.x = 0;
													uic.y = 0;
												}
										}
									}
									break;
								case 2:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										switch (m_MultiPages)
										{
											case 2 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = 0;
												}
												else
												{
													uic.x = 0;
													uic.y = 0;
												}
												break;
											case 4 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = ph;	
												}
												else
												{ 
													uic.x = pw;
													uic.y = 0;	
												}
												break;
											case 6 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = 0;	
												}
												else
												{
													uic.x = pw*2;
													uic.y = ph;	
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = 0;	
												}
												else
												{
													uic.x = pw*3;
													uic.y = ph;	
												}
										}
									}
									else
									{
										switch (m_MultiPages)
										{
											case 2 :
												uic.x = 0;
												uic.y = ph;
												break;
											case 4 :
												if (inSeroFlag == 0)
												{
													uic.x = pw;
													uic.y = ph;	
												}
												else
												{
													uic.x = pw;
													uic.y = 0;	
												}
												break;
											case 6 :
											case 8 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = ph;	
												}
												else
												{
													uic.x = pw;
													uic.y = 0;	
												}
										}
									}
									break;
								case 3:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										switch (m_MultiPages)
										{
											case 4 :
												if (inSeroFlag == 1)
												{ 
													uic.x = 0;
													uic.y = 0;
												}
												else
												{
													uic.x = 0;
													uic.y = ph;
												}
												break;
											case 6 :
												if (inSeroFlag == 1)
												{
													uic.x = pw*2;
													uic.y = 0;
												}
												else
												{
													uic.x = pw;
													uic.y = 0;	
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{
													uic.x = pw*2;
													uic.y = 0;
												}
												else
												{
													uic.x = pw*2;
													uic.y = 0;	
												}
												break;
										}
									}
									else
									{
										switch (m_MultiPages)
										{
											case 4 :
												if (inSeroFlag == 1)
												{
													uic.x = 0;
													uic.y = ph;
												}
												else
												{
													uic.x = 0;
													uic.y = 0;
												}
												break;
											case 6 :
											case 8 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = ph*2;
												}
												else
												{
													uic.x = 0;
													uic.y = ph;	
												}
												break;
										}
									}
									break;
								case 4:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										switch (m_MultiPages)
										{
											case 4 :
												if (inSeroFlag == 1)
												{ 
													uic.x = 0;
													uic.y = ph;	
												}
												else
												{
													uic.x = pw;
													uic.y = ph;			
												}
												break;
											case 6 :
												if (inSeroFlag == 1)
												{		
													uic.x = 0;
													uic.y = ph;	
												}
												else
												{
													uic.x = pw;
													uic.y = ph;
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{		
													uic.x = pw*3;
													uic.y = 0;	
												}
												else
												{
													uic.x = pw*2;
													uic.y = ph;
												}
												break;
										}
									}
									else
									{
										switch (m_MultiPages)
										{
											case 4 :
												if (inSeroFlag == 1)
												{
													uic.x = pw;
													uic.y = ph;	
												}
												else
												{
													uic.x = 0;
													uic.y = ph;			
												}
												break;
											case 6 :
												if (inSeroFlag == 1)
												{		
													uic.x = 0;
													uic.y = 0;	
												}
												else
												{
													uic.x = pw;
													uic.y = ph;
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{		
													uic.x = pw;
													uic.y = ph*3;	
												}
												else
												{
													uic.x = pw;
													uic.y = ph;
												}
												break;
										}
									}
									break;
								case 5:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										switch (m_MultiPages)
										{
											case 6 :
												if (inSeroFlag == 1)
												{		
													uic.x = pw;
													uic.y = ph;	
												}
												else
												{
													uic.x = 0;
													uic.y = 0;
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{		
													uic.x = 0;
													uic.y = ph;	
												}
												else
												{
													uic.x = pw;
													uic.y = 0;
												}
										}
									}
									else
									{
										switch (m_MultiPages)
										{
											case 6 :
												if (inSeroFlag == 1)
												{		
													uic.x = 0;
													uic.y = ph;	
												}
												else
												{
													uic.x = 0;
													uic.y = ph*2;
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{		
													uic.x = 0;
													uic.y = 0;	
												}
												else
												{
													uic.x = 0;
													uic.y = ph*2;
												}
										}
									}
									break;
								case 6:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										switch (m_MultiPages)
										{
											case 6 :
												if (inSeroFlag == 1)
												{		
													uic.x = pw*2;
													uic.y = ph;	
												}
												else
												{
													uic.x = 0;
													uic.y = ph;
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{		
													uic.x = pw;
													uic.y = ph;	
												}
												else
												{
													uic.x = pw;
													uic.y = ph;
												}
												break;
										}
									}
									else
									{
										switch (m_MultiPages)
										{
											case 6 :
												if (inSeroFlag == 1)
												{		
													uic.x = 0;
													uic.y = ph*2;	
												}
												else
												{
													uic.x = pw;
													uic.y = ph*2;
												}
												break;
											case 8 :
												if (inSeroFlag == 1)
												{		
													uic.x = 0;
													uic.y = ph;	
												}
												else
												{
													uic.x = pw;
													uic.y = ph*2;
												}
												break;
										}
									}
									break;
								case 7:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										if (inSeroFlag == 1)
										{
											uic.x = pw*2;
											uic.y = ph;
										}
										else
										{
											uic.x = 0;
											uic.y = 0;
										}
									}
									else
									{
										if (inSeroFlag == 1)
										{
											uic.x = 0;
											uic.y = ph * 2;
										}
										else
										{
											uic.x = 0;
											uic.y = ph * 3;
										}	
									}
									break;
								case 8:
									if (m_printJob.orientation == PrintJobOrientation.LANDSCAPE)
									{
										if (inSeroFlag == 1)
										{
											uic.x = pw*3;
											uic.y = ph;
										}
										else
										{
											uic.x = 0;
											uic.y = ph;
										}
									}
									else
									{
										if (inSeroFlag == 1)
										{
											uic.x = 0;
											uic.y = ph * 3;
										}
										else
										{
											uic.x = pw;
											uic.y = ph*3;
										}		
									}
									break;
							}
							
							uic.x += m_OffsetX * 2.835 / 10;
							uic.y += m_OffsetY * 2.835 / 10;
						}
			    	}

					// add print queue
					for (var pcp:int=0; pcp<(m_CopyType==0 ? m_Copy : 1); pcp++)
						m_printJob.addPage(_swfContainer, null, options);
						
					// restore	
					for(co=0; co<arr_uic.length; co++)
						(arr_uic[co]).removeChildAt(0);
					
					for(co=0; co<arr_loader.length; co++)
					{
						loader = arr_loader[co];
						
						loader.scaleX = loader.scaleY = 1;
						
						// ikchoi 2012.02.21
						loader.rotation = 0;
						
						if (curLoader == loader)
							_pageCanvas.addChild(loader);
					}
				}
			}
			
			m_printJob.send();
			m_printJob = null;
			
			_rdReport.gotoPage(curPage, curPage + _requestPages - 1);
					
			statusChangedHandler();
		}
		
		private function isRotation(loader : Loader) : int
		{
			var rotationFlag : int = 0;
			var seroFlag : int = 1;

			if (loader.width > loader.height)
			{
				seroFlag = 0;
			}

			if (m_ExpandType == 2)
			{
				switch (m_MultiPages)
				{
					case 1 :
					case 4 :
						if ((seroFlag == 0 && m_printJob.orientation != PrintJobOrientation.LANDSCAPE) || (seroFlag == 1 && m_printJob.orientation == PrintJobOrientation.LANDSCAPE))
						{							
							rotationFlag = 1;
						}
						break;
					case 2 :
					case 6 :
					case 8 :	
						if ((seroFlag == 0 && m_printJob.orientation == PrintJobOrientation.LANDSCAPE) || (seroFlag == 1 && m_printJob.orientation != PrintJobOrientation.LANDSCAPE))
						{							
							rotationFlag = 1;
						}
						break;
				}
			}
			else
			{
				if ((seroFlag == 0 && m_printJob.orientation != PrintJobOrientation.LANDSCAPE) || (seroFlag == 1 && m_printJob.orientation == PrintJobOrientation.LANDSCAPE))
				{
					rotationFlag = 1;
				}
			}
						
			return rotationFlag;			
		}
		
		
		private function addGlowFilter(img:Image):void
		{
			var filter : flash.filters.GlowFilter = new flash.filters.GlowFilter(0x111111, 1, 5, 5, 2, 1, false, false);
			img.filters = [ filter ];   
		}
		
		
		private function addDropShadow(img:Image):void
		{
			var filter : DropShadowFilter = new DropShadowFilter();
			filter.blurX = 4;
			filter.blurY = 4;
			filter.quality = 2;
			filter.alpha = 0.5;
			filter.angle = 45;
			filter.color = 0x202020;
			filter.distance = 6;
			filter.inner = false;
			img.filters = [ filter ];           
		}	
		
		public function getExecutionContext():LoaderContext
		{
			if(loaderCtx == null){
				loaderCtx = new LoaderContext();
				loaderCtx.applicationDomain = ApplicationDomain.currentDomain;

				if(loaderCtx.hasOwnProperty("allowLoadBytesCodeExecution")){
					loaderCtx["allowLoadBytesCodeExecution"] = true;
				}
				
			}
			return loaderCtx; 
		}
				
	}
}